gusucode.com > VC++ RingSDK界面库 > VC++ RingSDK界面库/code/libsrc/ringdib/dragrect.cpp
/********************************************************************** // // // ########## ###### ######### # ###### # // ############# ########### ######### ######### ### // ######## # ### ## ############# ## ## ##### # #### // #### ## ## ### ### ### # # ##### ##### // # ### # # ## ## ## ## ### // ## ###### ## ## #### #### # # ## // ######### ### ## ### ####### ###### ## ## ### // ###### ## ###### ## ## #### # ## #### // ####### ## ###### ## ### ## ## ### ###### // ######### ## ###### ## ###### ### ## ### # ##### // ## ###### ####### ### #### ## ## ####### ######## ## #### // ## #### ### # ### ### ## ########## ###### ## #### // ## ## ## ######### #### # ## // # ### // ## // ### // ## // // // RingSDK多媒体类库 ringdib.lib //作者:临风 // //版本:1.0 // //声明:本类库可以自由使用而不须对作者作出任何回报,但作者希望能得到 // 你的鼓励和支持。你可以对类库源码作出修改和改进,但希望你能在 // 修改的同时给作者一份同样的副本。 // 本类库不得用于任何商业用途,如确实需要,请与作者联系。 // //e-mail:ringphone@sina.com // //原文件名:dragrect.cpp // //说明:可移动/拖动矩形RingDragRect功能实现。 // // RingDragRect类似PhotoShop的选择矩形,在图象上画出一个 // 矩形,以动画显示,并可跟图象移动,缩放。因为图象在窗口 // 可以滚动,所以该类必须记录两个矩形坐标,一个在图象上 // 的矩形坐标m_rcDIB,该坐标只要矩形有效,是不会变的。一 // 个就是显示到窗口的坐标m_rcDC,只要图象有滚动,缩放, // 该坐标就必须根据在图象上的坐标重新计算,然后显示到 // 窗口。因为是动画显示矩形,所以有一个线程负责该矩形 // 的绘制。 // 因为矩形的显示跟窗口操作相关,所以在以下的窗口消息 // 中必须调用相应的成员函数: // WM_LBUTTONDOWN OnLButtonDown(LOWORD(lParam),HIWORD(lParam)); // WM_MOUSEMOVE OnMouseMove(LOWORD(lParam),HIWORD(lParam)); // WM_LBUTTONUP OnLButtonUp(LOWORD(lParam),HIWORD(lParam)); // WM_SIZE OnParentSize(LOWORD(lParam),HIWORD(lParam)); // WM_PAINT OnPaint(图象缩放比率(说明见dib_global.cpp)); // 特别说明:图象缩放操作时无须调用SetRate,该函数虽然 // 声明为public,但只要在WM_PAINT中调用OnPaint会自动 // 调用。一般无须调用。 // **********************************************************************/ #define MAKE_SELF_LIB #include "ringdib.h" RingDragRect::RingDragRect() { Init(); } RingDragRect::~RingDragRect() { DeleteObject(m_brush); if(hevent) { bQuitDraw = TRUE; SetEvent(hevent); } if(handleDraw) CloseHandle(handleDraw); CloseHandle(hevent); } void RingDragRect::Init() { memset(&m_rcDIB,0,sizeof(RECT)); memset(&m_rcDC,0,sizeof(RECT)); bInDrag = FALSE; bInMove = FALSE; bActived = FALSE; bInFirstAct = FALSE; m_nInSide = -1; scrx = scry = -9999; pt.x = -1; pt.y = -1; m_hWnd = NULL; m_dib = NULL; handleDraw = NULL; WORD b[16] = {0xf0f0,0xf0f0,0xf0f0,0xf0f0, 0x0f0f,0x0f0f,0x0f0f,0x0f0f}; BITMAP bm; bm.bmType = 0; bm.bmWidth = 8; bm.bmHeight = 8; bm.bmWidthBytes = 2; bm.bmPlanes = 1; bm.bmBitsPixel = 1; bm.bmBits = b; HBITMAP hbm = CreateBitmapIndirect(&bm); m_brush = CreatePatternBrush(hbm); DeleteObject(hbm); bQuitDraw = FALSE; hevent = CreateEvent(NULL,TRUE,TRUE,NULL); } int RingDragRect::left(int isDC/* = ON_DC*/) { if(isDC == ON_DC) return m_rcDC.left; else return m_rcDIB.left; } int RingDragRect::right(int isDC/* = ON_DC*/) { if(isDC == ON_DC) return m_rcDC.right; else return m_rcDIB.right; } int RingDragRect::top(int isDC/* = ON_DC*/) { if(isDC == ON_DC) return m_rcDC.top; else return m_rcDIB.top; } int RingDragRect::bottom(int isDC/* = ON_DC*/) { if(isDC == ON_DC) return m_rcDC.bottom; else return m_rcDIB.bottom; } BOOL RingDragRect::GetRect(LPRECT lprc,int isDC/* = ON_DC*/) { if(lprc) if(isDC == ON_DC) return CopyRect(lprc,&m_rcDC); else return CopyRect(lprc,&m_rcDIB); return FALSE; } void RingDragRect::OnLButtonDown(int x,int y) { pt.x = x; pt.y = y; ResetEvent(hevent); RECT rc; rc.left = m_rcDC.left; rc.top = m_rcDC.top; rc.right = m_rcDC.right + 1; rc.bottom = m_rcDC.bottom + 1; bInFirstAct = TRUE; InvalidateRect(m_hWnd,&rc,TRUE); if(bActived && m_dib) if(m_nInSide != -1) { if(m_nInSide == DRC_INSIDE) StartMove(x,y); else { SetCapture(m_hWnd); /* RECT rect; m_dib->GetDestRect(&rect); scrx = GetScrollPos(m_hWnd,SB_HORZ); scry = GetScrollPos(m_hWnd,SB_VERT); m_currX = m_dib->GetSrcX(); m_currY = m_dib->GetSrcY(); */ bActived = TRUE; bInDrag = TRUE; //bInFirstAct = TRUE; } return; } StartDrag(x,y); } void RingDragRect::StartDrag(int x,int y) { if(m_dib) { //SetCursor(LoadCursor(NULL,IDC_CROSS)); //if(bActived)// && bInFirstAct) // Draw(); SetCapture(m_hWnd); RECT rect; m_dib->GetDestRect(&rect); scrx = GetScrollPos(m_hWnd,SB_HORZ); scry = GetScrollPos(m_hWnd,SB_VERT); //检测边界 x = max(x,rect.left); x = min(x,rect.right); y = max(y,rect.top); y = min(y,rect.bottom); pt.x = x; pt.y = y; m_currX = m_dib->GetSrcX(); m_currY = m_dib->GetSrcY(); m_rcDC.left = m_rcDC.right = x; m_rcDC.top = m_rcDC.bottom = y; //设置相对于图象坐标 Get_OnDIBRect(m_dib,m_rate,&m_rcDC,&m_rcDIB); if(m_rate >=0) Get_OnDCRect(m_dib,m_rate,&m_rcDIB,&m_rcDC); //setDIBRect((LPPOINT)&rc,&pt); ptOrg.x = m_rcDC.left; ptOrg.y = m_rcDC.top; bActived = TRUE; bInDrag = TRUE; Draw(); } } void RingDragRect::Drag(int x,int y) { bInFirstAct = FALSE; if(m_dib && bActived && bInDrag) { Draw(); RECT rtd,rts; m_dib->GetDestRect(&rtd); m_dib->GetSrcRect(&rts); pt.x = x; pt.y = y; x = max(x,rtd.left); x = min(x,rtd.right); y = max(y,rtd.top); y = min(y,rtd.bottom); if(PtInRect(&rtd,pt)) { pt.x = x; pt.y = y; setDCRect(x,y); } else { //SetCursor(LoadCursor(NULL,IDC_CROSS)); int scx=0,scy = 0; if(pt.x < rtd.left && rts.left > 0) scx = -999; else if(pt.x > rtd.right && rts.right < m_dib->Width()) scx = 999; if(pt.y < rtd.top && rts.top > 0) scy = -999; else if(pt.y > rtd.bottom && rts.bottom < m_dib->Height()) scy = 999; if(scx != 0 || scy != 0) { ScrollParent(scx,scy); int sx = scrx; int sy = scry; scrx = GetScrollPos(m_hWnd,SB_HORZ); scry = GetScrollPos(m_hWnd,SB_VERT); sx -= scrx;// - sx; sy -= scry;// - sy; OffsetRect(&m_rcDC,sx,sy); ptOrg.x += sx; ptOrg.y += sy; } pt.x = x; pt.y = y; setDCRect(x,y); } Get_OnDIBRect(m_dib,m_rate,&m_rcDC,&m_rcDIB); if(m_rate >=0) Get_OnDCRect(m_dib,m_rate,&m_rcDIB,&m_rcDC); Draw(); } } void RingDragRect::StopDrag(int x,int y) { ReleaseCapture(); RECT rtd; m_dib->GetDestRect(&rtd); x = max(x,rtd.left); x = min(x,rtd.right); y = max(y,rtd.top); y = min(y,rtd.bottom); pt.x = x; pt.y = y; setDCRect(x,y); Get_OnDIBRect(m_dib,m_rate,&m_rcDC,&m_rcDIB); if(m_rate >=0) Get_OnDCRect(m_dib,m_rate,&m_rcDIB,&m_rcDC); bInDrag = FALSE; if(m_rcDC.left == m_rcDC.right || m_rcDC.top == m_rcDC.bottom) { bActived = FALSE; ResetEvent(hevent); } else SetEvent(hevent); } int RingDragRect::OnMouseMove(int x,int y) { if(bActived) { if(bInDrag) Drag(x,y); else if(bInMove) Move(x,y); else { RECT rect; CopyRect(&rect,&m_rcDC); InflateRect(&rect,3,3); pt.x = x; pt.y = y; if(PtInRect(&rect,pt)) { InflateRect(&rect,-6,-6); if(!PtInRect(&rect,pt)) { if(pt.x < rect.left) { if(pt.y < rect.top) { ptOrg.y = m_rcDC.bottom; m_nInSide = DRC_LU; } else if(pt.y > rect.bottom) { ptOrg.y = m_rcDC.top; m_nInSide = DRC_LD; } else { m_nInSide = -1; return -1; } ptOrg.x = m_rcDC.right; } else if(pt.x > rect.right) { if(pt.y < rect.top) { ptOrg.y = m_rcDC.bottom; m_nInSide = DRC_RU; } else if(pt.y > rect.bottom) { ptOrg.y = m_rcDC.top; m_nInSide = DRC_RD; } else { m_nInSide = -1; return -1; } ptOrg.x = m_rcDC.left; } } else m_nInSide = DRC_INSIDE; return m_nInSide; } else m_nInSide = -1; } } return m_nInSide; } void RingDragRect::StartMove(int x,int y) { SetCapture(m_hWnd); pt.x = x; pt.y = y; bInMove = TRUE; //bInFirstAct = TRUE; } void RingDragRect::Move(int x,int y) { bInFirstAct = FALSE; if(x > m_width || x < 0) x = pt.x; if(y > m_height || y < 0) y = pt.y; Draw(); if(m_rate >=0) { int ox,oy; ox = (x - pt.x)/(m_rate + 1); oy = (y - pt.y)/(m_rate + 1); if(ox != 0) pt.x = x; if(oy != 0) pt.y = y; if(ox != 0 || oy != 0) { OffsetRect(&m_rcDIB,ox,oy); Get_OnDCRect(m_dib,m_rate,&m_rcDIB,&m_rcDC); } } else { OffsetRect(&m_rcDC,x - pt.x,y - pt.y); pt.x = x; pt.y = y; } Draw(); } void RingDragRect::StopMove(int x,int y) { ReleaseCapture(); Get_OnDIBRect(m_dib,m_rate,&m_rcDC,&m_rcDIB); if(m_rate >=0) Get_OnDCRect(m_dib,m_rate,&m_rcDIB,&m_rcDC); bInMove = FALSE; bInFirstAct = FALSE; } void RingDragRect::OnLButtonUp(int x,int y) { m_nInSide = -1; if(bActived) { if(bInDrag) StopDrag(x,y); else if(bInMove) StopMove(x,y); if(handleDraw == NULL) handleDraw = NewThread((THREADPROC)DragRectDrawProc,this); Draw(); SetEvent(hevent); } } void RingDragRect::Draw() { if(bActived) { if(m_rcDC.left == m_rcDC.right && m_rcDC.top == m_rcDC.bottom) return; hDC = GetDC(m_hWnd); DrawFocusRect(hDC,&m_rcDC); ReleaseDC(m_hWnd,hDC); } } //跟画面滚动 void RingDragRect::OnPaint(int rate) { if(m_dib && bActived) { if(!bInDrag) { if(rate != m_rate) { SetRate(rate); scrx = GetScrollPos(m_hWnd,SB_HORZ); scry = GetScrollPos(m_hWnd,SB_VERT); } else { int sx = scrx; int sy = scry; scrx = GetScrollPos(m_hWnd,SB_HORZ); scry = GetScrollPos(m_hWnd,SB_VERT); if(scrx == 0 || scry == 0) SetRate(rate); else OffsetRect(&m_rcDC,sx - scrx,sy - scry); } } if(bInFirstAct) Draw(); } } //擦除矩形。必须先EnableDraw(FALSE)后才有效 void RingDragRect::Erase() { RECT rc; rc.left = m_rcDC.left; rc.top = m_rcDC.top; rc.right = m_rcDC.right + 1; rc.bottom = m_rcDC.bottom + 1; InvalidateRect(m_hWnd,&rc,TRUE); } void RingDragRect::Disable() { ResetEvent(hevent); Erase(); bActived = FALSE; } void RingDragRect::setDCRect(int x,int y) { // BOOL bSetAll = FALSE; if(ptOrg.x < x) { m_rcDC.left = ptOrg.x; m_rcDC.right = x; } else { m_rcDC.right = ptOrg.x; m_rcDC.left = x; } if(ptOrg.y < y) { m_rcDC.top = ptOrg.y; m_rcDC.bottom = y; } else { m_rcDC.bottom = ptOrg.y; m_rcDC.top = y; } //if(bSetAll) // setDIBRect((LPPOINT)&rc,(LPPOINT)&m_rcDC); //setDIBRect((LPPOINT)&rc+1,(LPPOINT)&m_rcDC+1); } void RingDragRect::setDIBRect(LPPOINT lpd,LPPOINT lps) { if(m_dib) { RECT rect; int x,y; m_dib->GetDestRect(&rect); x = lps->x; y = lps->y; if(m_rate >= 0) { x = (x - rect.left)/(m_rate+1); y = (y - rect.top)/(m_rate+1); lpd->x = m_dib->GetSrcX() + x; lpd->y = m_dib->GetSrcY() + y; } else { if(m_rate == -1) { lpd->x = m_dib->GetSrcX() + (x - rect.left)*4/3; lpd->x = m_dib->GetSrcY() + (y - rect.top)*4/3; } else { lpd->x = m_dib->GetSrcX() + (x - rect.left)*(-m_rate); lpd->y = m_dib->GetSrcY() + (y - rect.top)*(-m_rate); } } } } void RingDragRect::ScrollParent(int dx,int dy) { if(dx == 999) SendMessage(m_hWnd,WM_HSCROLL,MAKEWPARAM(SB_PAGERIGHT,0),0); else if(dx == -999) SendMessage(m_hWnd,WM_HSCROLL,MAKEWPARAM(SB_PAGELEFT,0),0); else { dx += GetScrollPos(m_hWnd,SB_HORZ); SendMessage(m_hWnd,WM_HSCROLL,MAKEWPARAM(SB_THUMBPOSITION,(short)max(0,dx)),0); } if(dy == 999) SendMessage(m_hWnd,WM_VSCROLL,MAKEWPARAM(SB_PAGEDOWN,0),0); else if(dx == -999) SendMessage(m_hWnd,WM_VSCROLL,MAKEWPARAM(SB_PAGEUP,0),0); else { dy += GetScrollPos(m_hWnd,SB_VERT); SendMessage(m_hWnd,WM_VSCROLL,MAKEWPARAM(SB_THUMBPOSITION,(short)max(0,dy)),0); } } void RingDragRect::EnableDraw(BOOL bDraw/* = TRUE*/) { if(hevent) if(bDraw) SetEvent(hevent); else ResetEvent(hevent); } void RingDragRect::SetRate(int rate) { m_rate = rate; Get_OnDCRect(m_dib,rate,&m_rcDIB,&m_rcDC); } DWORD DragRectDrawProc(RingDragRect* obj) { if(obj) { int x = 0,y = 0; HBRUSH oldbrush; while(WAIT_OBJECT_0 == WaitForSingleObject(obj->hevent,INFINITE)) { if(!obj->bQuitDraw) { HDC hDC = GetDC(obj->m_hWnd); oldbrush = (HBRUSH)SelectObject(hDC, obj->m_brush); SetBrushOrgEx(hDC,x,0,NULL); PatBlt(hDC,obj->m_rcDC.left,obj->m_rcDC.top,obj->m_rcDC.right - obj->m_rcDC.left,1,PATCOPY); PatBlt(hDC,obj->m_rcDC.left,obj->m_rcDC.bottom,obj->m_rcDC.right - obj->m_rcDC.left,1,PATCOPY); SetBrushOrgEx(hDC,0,y,NULL); PatBlt(hDC,obj->m_rcDC.right,obj->m_rcDC.top,1,obj->m_rcDC.bottom - obj->m_rcDC.top,PATCOPY); PatBlt(hDC,obj->m_rcDC.left,obj->m_rcDC.top,1,obj->m_rcDC.bottom - obj->m_rcDC.top,PATCOPY); x ++; y ++; if(x > 8) { x -= 8; y -= 8; } SelectObject(hDC,oldbrush); ReleaseDC(obj->m_hWnd,hDC); } else break; Sleep(250); } } return 100; }